package com.accp.ssmoa.controller;


import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.accp.ssmoa.pojo.ActivitiProcdef;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;


@Controller
@Scope("prototype")
@RequestMapping("/admin/workflow")
public class WorkflowController {

	// 获取仓库服务对象
    @Autowired  
    private RepositoryService repositoryService;	
	
	
	
	//初始化工作流程页面
	@RequestMapping("/getListPage")
	public String getListPage(HttpServletRequest request) {
		
		//存储面包屑导航的值进request作用域
		request.setAttribute("pageTitle","流程管理");
		
		request.setAttribute("url","/admin/workflow/getListPage");
		
		request.setAttribute("nowBread","管理");
		
		
		return "workflow/list";
	}
	

	// 分页显示流程信息
	@RequestMapping(value = "/listData", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
	@ResponseBody
	public Map<String, Object> listData(@RequestBody JSONObject jsonObj) {

		// 取出前台传过来的封装在json格式里面的数据
		Integer pageSize = jsonObj.getIntValue("pageSize"); // 每页显示数据条数
		Integer startRow = jsonObj.getIntValue("startRow"); // 当前页码

		// 总数据数		
		int totalsize = (int) repositoryService.createProcessDefinitionQuery().count();
		Map<String, Object> map = new HashMap<String, Object>();

		List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().listPage(startRow, pageSize);

		List<ActivitiProcdef> resultList=new ArrayList<ActivitiProcdef>();
		
		
		for (ProcessDefinition process : list) {
			
			ActivitiProcdef procdef=new ActivitiProcdef();
			procdef.setId(process.getId());
			procdef.setKey(process.getKey());
			
			procdef.setResourceName(process.getResourceName());
			procdef.setDeploymentId(process.getDeploymentId());
			procdef.setVersion(process.getVersion());
			procdef.setDgrmResourceName(process.getDiagramResourceName());
			
			if (process.isSuspended()) {
				procdef.setSuspensionState(0);
			} else {
				procdef.setSuspensionState(1);
			}

			Deployment deployment= repositoryService.createDeploymentQuery().deploymentId(process.getDeploymentId()).singleResult();
			procdef.setDeployTime(deployment.getDeploymentTime());
			procdef.setName(deployment.getName());
			
			resultList.add(procdef);
			
		}
		
		// total表示数据总数，rows表示需要显示的数据。必须按照这种格式返回才行。
		map.put("total", totalsize);
		map.put("rows", resultList);

		return map;
	}
	
	/**
	 * 读取资源，通过部署ID
	 * @param processDefinitionId  流程定义ID
	 * @param resourceType 资源类型(xml|image)
	 * @param response
	 * @throws IOException 
	 * @throws Exception
	 */
    @RequestMapping("resourceRead")
    public void resourceRead(@RequestParam("procDefId") String procDefId,@RequestParam("resType") String resType,
    		HttpServletResponse response){
   
    	ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(procDefId).singleResult();
    	InputStream resourceAsStream=null;
    	
    	
		String resourceName = "";
		if (resType.equals("image")) {
			resourceName = processDefinition.getDiagramResourceName();
		} else if (resType.equals("xml")) {
			resourceName = processDefinition.getResourceName();
		}
		
		resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);
		
/*		byte[] b = new byte[1024];
		int len = -1;
		while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
			response.getOutputStream().write(b, 0, len);
		} */
		
        try{
            byte[] buffer = new byte[1024];
            int bytesRead = 0;
            do {
                bytesRead = resourceAsStream.read(buffer, 0, buffer.length);
                response.getOutputStream().write(buffer, 0, bytesRead);
            } while (bytesRead == buffer.length);

        } catch (Exception e) {  
        	
        	e.printStackTrace();
        }finally{
            try {
                if (resourceAsStream != null) {
                	resourceAsStream.close();
                }
                response.getOutputStream().flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    	
	}	
	
	/*需要权限控制的操作*/
	
	// 实现删除
	@RequestMapping(value = "/delete")
	@ResponseBody
	public Map<String, Object> delete(@RequestParam(value = "deployid") String deployid) {

		Map<String, Object> result = new HashMap<String, Object>();

		repositoryService.deleteDeployment(deployid,true);

		result.put("success", true);
		result.put("message", "删除成功");


		return result;

	}	


	//实现挂起、激活
    @RequestMapping(value = "updateState") 
    @ResponseBody
    public Map<String, Object> updateState(@RequestParam("state") String state, 
    		@RequestParam("defid") String defid) {  
    	
    	Map<String, Object> result=new HashMap<String, Object>();
    	
    	
    	
/*    	使用activateProcessDefinitionById实现对流程定义的激活
    	使用suspendProcessDefinitionById实现对流程定义的挂起
    	
    	各参数含义如下：
    	String processDefinitionId——————————————————流程定义的ID
    	boolean suspendProcessInstances/includeProcessInstances—————是否同时激活/挂起对应的流程实例
    	Date suspensionDate/activationDate—————————设置定时器来实现定时挂起或者激活*/
    	
        if (state.equals("active")) {  
            
            repositoryService.activateProcessDefinitionById(defid, true, null);  
            result.put("message", "已激活ID为[" + defid + "]的流程定义");
        } else if (state.equals("suspend")) {  
            repositoryService.suspendProcessDefinitionById(defid, true, null);  
            result.put("message", "已挂起ID为[" + defid + "]的流程定义");

        }  
        
        
        result.put("success", true);
        
        
        return result;  
    } 

    
    //转换成模型
    @RequestMapping("convertToModel")
    @ResponseBody
	public Map<String, Object> convertToModel(@RequestParam("defid") String defid) throws UnsupportedEncodingException, XMLStreamException{
    	
    	
    	Map<String, Object> result=new HashMap<String, Object>();
    	
    	try {
			//根据id获取流程定义
			ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(defid).singleResult();
			
			
			//获取流程定义的bpmn.xml文件
			InputStream bpmnStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(),
			processDefinition.getResourceName());
			
			//解析bpmn.xml文件，获取节点信息
			XMLInputFactory xif = XMLInputFactory.newInstance();
			InputStreamReader in = new InputStreamReader(bpmnStream, "UTF-8");
			XMLStreamReader xtr = xif.createXMLStreamReader(in);
			BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr);

			BpmnJsonConverter converter = new BpmnJsonConverter();
			ObjectNode modelNode = converter.convertToJson(bpmnModel);
			
			//根据解析出来的信息创建模型
			Model modelData = repositoryService.newModel();
			modelData.setKey(processDefinition.getKey());
			modelData.setName(processDefinition.getName());
			modelData.setCategory(processDefinition.getCategory());//.getDeploymentId());
			modelData.setDeploymentId(processDefinition.getDeploymentId());
			modelData.setVersion(Integer.parseInt(String.valueOf(repositoryService.createModelQuery().modelKey(modelData.getKey()).count()+1)));

			ObjectNode modelObjectNode = new ObjectMapper().createObjectNode();
			modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, processDefinition.getName());
			modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, modelData.getVersion());
			modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, processDefinition.getDescription());
			modelData.setMetaInfo(modelObjectNode.toString());

			//保存模型
			repositoryService.saveModel(modelData);
			repositoryService.addModelEditorSource(modelData.getId(), modelNode.toString().getBytes("utf-8"));
		
			result.put("message", "转换模型成功");
			result.put("type", "success");
    	} catch (NumberFormatException e) {
    		result.put("message", "转换模型失败");
    		result.put("type", "danger");
			e.printStackTrace();
		} catch (FactoryConfigurationError e) {
			result.put("message", "转换模型失败");
			result.put("type", "danger");
			e.printStackTrace();
		}
		
		return result;
	}
    


}
